/**
 * 供列表页使用
 */
import {reactive, Ref, watch, ref} from 'vue';
import {ColumnInfo, ColumnOption, FilterInfo, PaginationInfo, FpsResp} from '../defs/comm'
import _ from 'lodash'

// FPS相关信息定义(响应式)
interface FpsInfo {
  // 分页信息
  paginationInfo: PaginationInfo,
  // 列选项
  columnsInfo: ColumnInfo[],
  // 可见的列
  visibleColumns: string[],
  // 过滤条件选项
  filtersInfo: Record<string, FilterInfo>,
  // 总条数
  totalAmount: number
}

// FPS相关辅助方法定义
interface FpsAssist {
  // 保存过滤条件选项
  saveFilterOptions: (visibleFilterOptions: string[]) => void,
  // 保存列选项
  saveColOptions: (colOptions: ColumnOption[]) => void,
  // 将FPS信息保存到Session中，以便在页面重新加载时还能保持这些查询条件
  saveFpsReq: (fpsReq: Record<string, any>) => void,
  // 对FPS返回的一般处理方法
  handleGenericFpsResp: (resp: Record<string, any>) => void,
  // 将pageSize保存到localStorage中
  onPageSizeChanged: (pageSize: number) => void,

  // 排序动作的回调方法,具体参考：https://quasar.dev/vue-components/table#qtable-api
  onDataTableRequest: (prop: {
    pagination: {
      sortBy: string,
      descending: boolean
    }
  }) => void
}

// FPS导航方法定义
interface FpsNav {
  // 转至创建
  gotoCreate: () => void,
  // 转至详情
  gotoDetail: (itemId: string, evt?: PointerEvent) => void,
  // 转至编辑
  gotoEdit: (itemId: string, evt?: PointerEvent) => void,
  // 翻页
  gotoPage: (pageNo: number, pageSize: number) => void,
}

interface FpsSuite {
  // FPS相关信息(Reactive)
  fpsInfo: FpsInfo,
  // FPS辅助方法
  fpsAssist: FpsAssist,
  // FPS导航方法
  fpsNav: FpsNav,
  // 搜索条是否显示(Ref)
  searchBarVisibility: Ref<boolean>
}

/**
 * 调用此方法初始化FPS，并返回相关变量及方法
 * @param pageName 通常与routeName相同
 * @param viewRouteName 查看的路由
 * @param createRouteName 创建的路由
 * @param editRouteName 编辑的路由
 * @param fpsReq FPS请求体(reactive)
 * @param columnsDefine 列定义(初始)
 * @param filtersDefine 过滤条件定义
 * @param loadListData 加载数据的方法,参数: 0-不重置分页和排序; 1-重置分页；2-重置分页和排序
 * @param firstLoad 首次是否调用loadListData
 */
export function useFpsHelper(pageName: string,
                             viewRouteName: string | null,
                             createRouteName: string | null,
                             editRouteName: string | null,
                             fpsReq: Record<string, any> | null,
                             columnsDefine: ColumnInfo[] | null,
                             filtersDefine: Record<string, FilterInfo> | null,
                             loadListData: (resetFpsReq?: number) => void,
                             firstLoad?: boolean): FpsSuite {
  // region 几个key，内部使用
  // 当前fps条件的key
  const fpsReqSessionStorageKey = pageName + '_fpsreq'
  // 每页条数的key
  const pageSizeLocalStorageKey = pageName + '_pagesize'
  // 数据表列选项的key
  const tableColOptionsKey = pageName + '_tbcolopt'
  // 查询条选项的key
  const visibleFilterOptionsKey = pageName + '_filteropt'
  // 搜索条显示与否Key
  const searchBarVisibilityKey = pageName + '_sbvisibility'
  // endregion

  // region 供外部调用的方法
  // 保存过滤条件选项
  const saveFilterOptions = function (visibleFilterOptions: string[]) {
    window.localStorage.setItem(visibleFilterOptionsKey, JSON.stringify(visibleFilterOptions))
  }

  // 保存列选项
  const saveColOptions = function (colOptions: ColumnOption[]) {
    window.localStorage.setItem(tableColOptionsKey, JSON.stringify(colOptions))
  }
  // 保存页尺寸
  const savePageSize = function (pageSize: number) {
    window.localStorage.setItem(pageSizeLocalStorageKey, pageSize.toString())
  }
  // 将FPS信息保存到Session中，以便在页面重新加载时还能保持这些查询条件
  const saveFpsReq = function (fpsReq: Record<string, any>) {
    window.sessionStorage.setItem(fpsReqSessionStorageKey, JSON.stringify(fpsReq))
  }
  // 此方法能够处理一般性的FPS响应，需要这些前提：
  // * 组件(页面)中的请求体叫fpsReq (其实不一定要求真的有FPS信息)
  // * 组件(页面)中的分页信息叫paginationInfo (可选)
  const handleGenericFpsResp = function (resp: Record<string, any>) {
    if (fpsReq) {
      $f.misc.simpleAssign(fpsReq, resp)
    }
    const fpsResp = resp as FpsResp
    fpsSuite.fpsInfo.totalAmount = fpsResp.totalAmount
    fpsSuite.fpsInfo.paginationInfo.rowsNumber = fpsResp.totalAmount
    fpsSuite.fpsInfo.paginationInfo.page = fpsResp.pageNo
    fpsSuite.fpsInfo.paginationInfo.rowsPerPage = fpsResp.pageSize
    fpsSuite.fpsInfo.paginationInfo.sortBy = fpsResp.orderBy
    fpsSuite.fpsInfo.paginationInfo.descending = fpsResp.isDescending
  }

  // 转至创建
  const gotoCreate = function () {
    if (!createRouteName) {
      console.warn('fpsHelper: createRouteName未正确设置')
      return
    }
    void $f.router.push({name: createRouteName})
  }
  // 转至详情
  const gotoDetail = (itemId: string, evt?: PointerEvent) => {
    if (!viewRouteName) {
      console.warn('fpsHelper: viewRouteName未正确设置')
      return
    }
    const param = {name: viewRouteName, params: {itemId: itemId}}
    if (evt?.shiftKey) {
      const urlPath = $f.router.resolve(param)
      window.open(urlPath.href, '_blank')
    } else {
      void $f.router.push(param)
    }
  }
  // 转至编辑
  const gotoEdit = (itemId: string, evt?: PointerEvent) => {
    if (!editRouteName) {
      console.warn('fpsHelper: editRouteName未正确设置')
      return
    }
    if (evt?.shiftKey) {
      const param = {name: editRouteName, params: {itemId: itemId}}
      const urlPath = $f.router.resolve(param)
      window.open(urlPath.href, '_blank')
    } else {
      const param = {name: editRouteName, params: {itemId: itemId}, state:{isFromList: 'true'}}
      void $f.router.push(param)
    }
  }
  // Quasar框架的QTable的request事件的参数定义
  const onDataTableRequest = function (prop: {
    pagination: {
      sortBy: string,
      descending: boolean
    }
  }) {
    if (fpsReq) {
      fpsReq.orderBy = prop.pagination.sortBy
      fpsReq.isDescending = prop.pagination.descending
    }
    loadListData(1)
  }

  // 将pageSize保存到localStorage中
  const onPageSizeChanged = function (pageSize: number) {
    if (fpsReq) {
      fpsReq.pageSize = pageSize
    }
    savePageSize(pageSize)
    loadListData(0)
  }

  // 翻页
  const gotoPage = function (pageNo: number, pageSize: number) {
    if (fpsReq) {
      fpsReq.pageNo = pageNo
      fpsReq.pageSize = pageSize
    }
    loadListData(0)
  }

  const searchBarVisibility = ref(true)

  // 尝试还原之前的状态
  searchBarVisibility.value = window.localStorage.getItem(searchBarVisibilityKey) !== 'false'

  watch(searchBarVisibility, function (newVal, oldVal) {
    if (oldVal != null && oldVal !== newVal) {
      window.localStorage.setItem(searchBarVisibilityKey, newVal.toString())
    }
  })
  // endregion

  // region 初始化时候的处理

  // 判断是否清空sessionStorage
  if (history.state.keepFpsSession!=='true') {
    window.sessionStorage.removeItem(fpsReqSessionStorageKey)
  }

  // 列选项
  let columnsInfo: ColumnInfo[] = []
  // 显示的列
  let visibleColumns: string[] = []
  // region 列选项
  // const columnsInfo = computed(() => {
  //   if (columnsDefine) {
  //     const tableColOptionsJson = window.localStorage.getItem(tableColOptionsKey)
  //     if (tableColOptionsJson) {
  //       const tableColOptions = JSON.parse(tableColOptionsJson) as ColumnOption[]
  //       visibleColumns = _.map(_.reject(tableColOptions, function (o) {
  //           return !o.visible
  //         }),
  //         'name'
  //       )
  //       return $f.misc.sortByKeys(columnsDefine.value, 'name', _.map(tableColOptions, 'name')) as ColumnInfo[]
  //     } else {
  //       visibleColumns = _.map(
  //         _.reject(columnsDefine.value, function (o) {
  //           return !o.defVisible
  //         }),
  //         'name'
  //       )
  //       return columnsDefine.value
  //     }
  //   } else {
  //     return []
  //   }
  // })
  // endregion
  // 数据表列选项恢复
  if (columnsDefine) {
    const tableColOptionsJson = window.localStorage.getItem(tableColOptionsKey)
    if (tableColOptionsJson) {
      const tableColOptions = JSON.parse(tableColOptionsJson) as ColumnOption[]
      columnsInfo = $f.misc.sortByKeys(columnsDefine, 'name', _.map(tableColOptions, 'name')) as ColumnInfo[]
      visibleColumns = _.map(_.reject(tableColOptions, function (o) {
          return !o.visible
        }),
        'name'
      )
    } else {
      columnsInfo = columnsDefine
      visibleColumns = _.map(
        _.reject(columnsDefine, function (o) {
          return !o.defVisible
        }),
        'name'
      )
    }
  }

  //  过滤条件选项信息
  let filtersInfo: Record<string, FilterInfo> = {}
  // 过滤条件选项恢复
  if (filtersDefine) {
    filtersInfo = _.cloneDeep(filtersDefine) //重新创建一个对象，不希望改变原先传入的参数
    const filterOptionsJson = window.localStorage.getItem(visibleFilterOptionsKey)
    if (filterOptionsJson) {
      const filterOptions = JSON.parse(filterOptionsJson) as string[]
      _.forEach(filtersInfo, (value, key) => {
        value.show = _.indexOf(filterOptions, key) >= 0
      })
    }
  }

  let pageSize = 40
  // FPS选项恢复
  if (fpsReq) {
    // pageSize恢复
    const pageSizeStr = window.localStorage.getItem(pageSizeLocalStorageKey)
    if (pageSizeStr) {
      const pageSizeRecover = parseInt(pageSizeStr)
      if(Number.isInteger(pageSizeRecover)){
        pageSize = pageSizeRecover
      }
      fpsReq.pageSize = pageSize
    }

    // 从sessionStorage中获取fps参数
    const fpsReqOfSessionJson = window.sessionStorage.getItem(fpsReqSessionStorageKey)
    if (fpsReqOfSessionJson) {
      const fpsReqOfSession = JSON.parse(fpsReqOfSessionJson) as Record<string, any>
      $f.misc.simpleAssign(fpsReq, fpsReqOfSession)
      // 按常理刷新页面history.state应该被清空,但是不知道为啥这里没有清理,F5以后还是true 这里做一下手动处理改成false不然查询条件会一直
      // 保存在这个路由上直到路由变动
      history.state.keepFpsSession = false
    }
  }

  // 首次加载数据
  if (firstLoad !== false) {
    loadListData(0)
  }

  // endregion

  const fpsSuite: FpsSuite = {
    fpsInfo: reactive({
      paginationInfo: {
        // 页码
        page: 1,
        // 每页多少条
        rowsPerPage: pageSize,
        // 总条数
        rowsNumber: 0,
        // 是否倒序
        descending: false,
        // 按什么排序
        sortBy: ''
      },
      columnsInfo,
      visibleColumns,
      filtersInfo,
      totalAmount:0
    }),
    fpsAssist: {
      saveFilterOptions,
      saveColOptions,
      saveFpsReq,
      handleGenericFpsResp,
      onPageSizeChanged,
      onDataTableRequest
    },
    fpsNav: {
      gotoCreate,
      gotoEdit,
      gotoDetail,
      gotoPage
    },
    searchBarVisibility
  }
  return fpsSuite
}
